﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using HandyControl.Controls;
using HandyControl.Data;
using HarfBuzzSharp;
using LiveChartsCore.Kernel;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.VisualElements;
using LiveChartsCore.SkiaSharpView.WPF;
using MeasureAbstract.IFarfieldMeasure;
using MeasureAbstract.ISilentAreaMeasure;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using LiveChartsCore.SkiaSharpView.Painting;
using System.Drawing;
using System.ComponentModel;
using System.Reflection;
using NPOI.DDF;
using 紧缩场反射面装调测试系统.Views;
using System.Text.Json;
using MeasureAbstract.Base;

namespace 紧缩场反射面装调测试系统.ViewModels
{
    public partial class DataProcessViewModel:ObservableObject
    {
        private ISilentAreaMeasure? _Measure;
        public ISilentAreaMeasure? Measure
        {
            get { return _Measure; }
            set { SetProperty(ref _Measure, value); }
        }


        public DataProcessViewModel() 
        {
            LVC.ZoomMode = LiveChartsCore.Measure.ZoomAndPanMode.X;
            LVC.ChartPointPointerDown += LVC_ChartPointPointerDown;
            LVC.TooltipPosition = LiveChartsCore.Measure.TooltipPosition.Top;
            LVC.Title = new LabelVisual
            {
                Text = DataType,
                TextSize = 20,
                Padding = new LiveChartsCore.Drawing.Padding(5),
                Paint = new SolidColorPaint(SKColors.DarkSlateGray)

            };
        }

        private string ValueToUnit(double value)
        {
            double F = value;
            string F_str = "";
            if (F / 1000000000 >= 1)
            {
                //GHz
                F_str = (F / 1000000000).ToString() + "GHz";
            }
            else if (F / 1000000 >= 1)
            {
                //MHz
                F_str = (F / 1000000).ToString() + "MHz";
            }
            else if (F / 1000 >= 1)
            {
                //KHz
                F_str = (F / 1000).ToString() + "KHz";
            }
            else
            {
                F_str = F.ToString() + "Hz";
            }
            return F_str;
        }
        private void LVC_ChartPointPointerDown(LiveChartsCore.Kernel.Sketches.IChartView chart, ChartPoint? point)
        {
            if(point == null) return;

            Fix_Position = point.Coordinate.SecondaryValue;
            Fix_Frequency = double.Parse(point.Context.Series.Name);
        }


        #region 与图表相关的操作
        public CartesianChart LVC { get; set; } = new CartesianChart();

        [RelayCommand]
        public void AddLine(string Name)
        {
            //设置曲线的属性（名称一般设置为频率值）
            //设置曲线的数据
            //将曲线添加到图表数据
            bool Y = false;
            foreach (var temp in LVC.Series)
            {
                if (temp.Name == Name)
                {
                    //曲线已存在
                    Y = true;
                }
            }

            if (!Y)
            {
                var aaa = LVC.Series.ToList();
                var temp = new LineSeries<DataItem>
                {
                    GeometrySize = 4,
                    Name = Name,
                    Fill = null,
                    YToolTipLabelFormatter = (p) => { return $"( {p.Coordinate.SecondaryValue.ToString("F3")} , {p.Coordinate.PrimaryValue.ToString("F3")} )"; },
                    Values = DataDictFrequency_PositionCollection[double.Parse(Name)],
                    
                };
                //添加曲线
                aaa.Add(temp);
                LVC.Series = aaa.ToArray();
                SwitchDataType(DataType);

            }

        }

        [RelayCommand]
        public void RemoveLine(string Name)
        {
            //根据名称找到曲线（名称一般设置为频率值）
            //移除曲线
            bool Y = false;
            var A = LVC.Series.ToList();
            foreach (var temp in A)
            {
                if (temp.Name == Name)
                {
                    //曲线已存在
                    Y = true;
                    A.Remove(temp);
                    LVC.Series = A.ToArray();
                    break;
                }
            }


        }

        [RelayCommand]
        public void SwitchDataType(string Type)
        {
            //变更图表显示的变量
            //更改图表标题
            //查找当前有几条曲线，记录下来
            //将新曲线的数据添加到图表
            if (Type == "对数幅度")
            {
                var bb = LVC.Title as LabelVisual;
                bb.Text = Type;

                foreach (var temp in LVC.Series)
                {
                    var temp2 = temp as LineSeries<DataItem>;
                    temp2.Mapping = (city, chartPoint) =>
                    {
                        return new Coordinate(city.Position, city.LogarithmicAmplitude);
                    };
                }
            }
            else if (Type == "相位")
            {
                var bb = LVC.Title as LabelVisual;
                bb.Text = Type;
                foreach (var temp in LVC.Series)
                {
                    var temp2 = temp as LineSeries<DataItem>;
                    temp2.Mapping = (city, chartPoint) =>
                    {
                        return new Coordinate(city.Position, city.Phase);
                    };
                }
            }
            else if (Type == "线性幅度")
            {
                var bb = LVC.Title as LabelVisual;
                bb.Text = Type;
                foreach (var temp in LVC.Series)
                {
                    var temp2 = temp as LineSeries<DataItem>;
                    temp2.Mapping = (city, chartPoint) =>
                    {
                        return new Coordinate(city.Position, city.LinearAmplitude);
                    };
                }
            }
            else if (Type == "实部")
            {
                var bb = LVC.Title as LabelVisual;
                bb.Text = Type;
                foreach (var temp in LVC.Series)
                {
                    var temp2 = temp as LineSeries<DataItem>;
                    temp2.Mapping = (city, chartPoint) =>
                    {
                        return new Coordinate(city.Position, city.RealPart);
                    };
                }
            }
            else if (Type == "虚部")
            {
                var bb = LVC.Title as LabelVisual;
                bb.Text = Type;
                foreach (var temp in LVC.Series)
                {
                    var temp2 = temp as LineSeries<DataItem>;
                    temp2.Mapping = (city, chartPoint) =>
                    {
                        return new Coordinate(city.Position, city.ImaginaryPart);
                    };
                }
            }
            else if (Type == "驻波比")
            {
                var bb = LVC.Title as LabelVisual;
                bb.Text = Type;
                foreach (var temp in LVC.Series)
                {
                    var temp2 = temp as LineSeries<DataItem>;
                    temp2.Mapping = (city, chartPoint) =>
                    {
                        return new Coordinate(city.Position, city.StandingWaveRatio);
                    };
                }
            } 
            else if (Type == "群延时")
            {
                var bb = LVC.Title as LabelVisual;
                bb.Text = Type;
                foreach (var temp in LVC.Series)
                {
                    var temp2 = temp as LineSeries<DataItem>;
                    temp2.Mapping = (city, chartPoint) =>
                    {
                        return new Coordinate(city.Position, city.GroupDelay);
                    };
                }
            }
            else
            {
                if (string.IsNullOrEmpty(Type)) return;
                throw new Exception($"不支持的数据类型{Type}");
            }

        }
        #endregion



        #region 与外部数据文件相关的操作

        public string FilePath
        {
            get { return _FilePath; }
            set
            {
                SetProperty(ref _FilePath, value);
                //更新图表
                if (!string.IsNullOrEmpty(value))
                {
                    ReadDatas();
                }
            }
        }
        private string _FilePath = "";


        List<string> AlreadyExistFiles = new List<string>();

        public async void ReadDatas()
        {
            await Task.Run(() =>
            {
                string[] Files = FilePath.Split("\n");
                foreach (string File in Files)
                {
                    if (File != "")
                    {
                        //验证数据文件是否有效，给出提示
                        if (!System.IO.File.Exists(File))
                        {
                            Growl.Warning($"{File}不存在!");
                            continue;
                        }

                        if (AlreadyExistFiles.Contains(File))
                        {
                            Growl.Warning($"{File}已经存在!");
                            continue;
                        }
                        ResetData();
                        DataManage.ReadFromFile(File, out MeasureData);
                        if (MeasureData.DocumentIdentificationMark != "CP_DATA")
                        {
                            Growl.Warning($"{File}不是有效的数据文件!\n文件识别标记{MeasureData.DocumentIdentificationMark}不匹配！");
                            continue;
                        }

                        AlreadyExistFiles.Add(File);
                        //解析数据文件，将包含的数据格式填入下面的选项中
                        DataClassify(MeasureData,ref DataDictFrequency_PositionCollection);
                    }
                }

                //保存文件名到处理后的路径
                SaveAsName = FilePath;
                //读取文件完毕
                GrowlInfo Info = new GrowlInfo();
                Info.WaitTime = 0;
                Info.Message = "读取文件完毕!";
                Growl.Success(Info);
            });
        }

        #endregion


        #region 与当前测量数据相关

        static T DeepCopy<T>(T obj)
        {
            string json = JsonSerializer.Serialize<T>(obj);

            // 反序列化
            return JsonSerializer.Deserialize<T>(json);
        }
        //将测量数据复制过来，不是引用
        public MeasureData CopyData(MeasureData Source)
        {
            return DeepCopy<MeasureData>(Source);
        }

        public async void LoadData(MeasureData Source)
        {
            await Task.Run(() => 
            {
                Clear();
                //从测量中复制数据
                MeasureData = CopyData(Source);
                //数据分类
                DataClassify(MeasureData, ref DataDictFrequency_PositionCollection);
          
            });

            //另存文件名
            SaveAsName = Measure.DataFilePath;

            GrowlInfo Info = new GrowlInfo();
            Info.WaitTime = 0;
            Info.Message = "数据加载完毕!";
            Growl.Success(Info);
        }


        #endregion


        #region 与数据处理相关

        MeasureData MeasureData = new MeasureData();//用来保存从文件中读取到的或是从测量页面发送过来的原始数据
        public Dictionary<double, ObservableCollection<DataItem>> DataDictFrequency_PositionCollection; //原始数据解析之后得到的按频点分类的数据


        public ObservableCollection<string> FrequencyList  //存放频点列表
        {
            get { return _FrequencyList; }
            set
            {
                SetProperty(ref _FrequencyList, value);
            }
        }
        private ObservableCollection<string> _FrequencyList = new ObservableCollection<string>();


        [ObservableProperty]
        public ObservableCollection<string> selectFrequencyList = new ObservableCollection<string>();




        //将原始数据按频点分类
        public void DataClassify(MeasureData Source,ref Dictionary<double, ObservableCollection<DataItem>> Dest)
        {
            if (Source.DataItems == null)
            {
                Growl.Warning($"包含0条数据!");
                return;
            }
            if (Source.DataItems.Count == 0)
            {
                Growl.Warning($"包含0条数据!");
                return;
            }
            if (Dest == null)
            {
                Dest = new Dictionary<double, ObservableCollection<DataItem>>();
            }
            else
            {
                Dest.Clear();
            }
            foreach (var Item in Source.DataItems)
            {
                DataManage.AddDataItemToFrequencyBaseDict(Item, ref Dest);
            }
            var temp2 = Dest.Keys;
            Application.Current.Dispatcher.Invoke(() =>
            {

                foreach (var temp in Source.DataFormat.Split(";"))
                {
                    if(String.IsNullOrEmpty(temp)) continue;
                    DataTypeList.Add(temp.ToString());
                }
                DataType = DataTypeList[0];
                FrequencyList.Clear();
                foreach (var temp in temp2)
                {
                    FrequencyList.Add(temp.ToString());
                }
                SelectFrequencyList = new ObservableCollection<string>() { FrequencyList.FirstOrDefault() };
        });


        }

        [ObservableProperty]
        public ObservableCollection<string> dataTypeList = new ObservableCollection<string>();

        private string dataType = "";
        public string DataType
        {
            get
            {
                return dataType;
            }
            set
            {
                SetProperty(ref dataType, value);
                SwitchDataType(dataType);
            }
        }

        [RelayCommand]
        public void SelectionChange(SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count > 0)
            {
                foreach (var item in e.AddedItems)
                {
                    AddLine(item.ToString());
                }
            }

            if (e.RemovedItems.Count > 0)
            {
                foreach (var item in e.RemovedItems)
                {
                    RemoveLine(item.ToString());
                }
            }
        }

        [RelayCommand]
        public void Clear()
        {
            FilePath = "";
            DataDictFrequency_PositionCollection = new Dictionary<double, ObservableCollection<DataItem>>();
            FrequencyList = new ObservableCollection<string>();
            SelectFrequencyList = new ObservableCollection<string>();
            MeasureData = new MeasureData();
            AlreadyExistFiles.Clear();
            DataTypeList = new ObservableCollection<string>();
            DataType = "";
        }

        public void ResetData()
        {
            DataDictFrequency_PositionCollection = new Dictionary<double, ObservableCollection<DataItem>>();
            FrequencyList = new ObservableCollection<string>();
            SelectFrequencyList = new ObservableCollection<string>();
            MeasureData = new MeasureData();
            AlreadyExistFiles.Clear();
            DataTypeList = new ObservableCollection<string>();
            DataType = "";
        }

        [ObservableProperty]
        private string saveAsName = "";

        [RelayCommand]
        public void SaveData()
        {
            //初始化保存数据的变量
            if(MeasureData==null)
            {
                MeasureData = new MeasureData();
            }
            if(MeasureData.DataItems==null)
            {
                MeasureData.DataItems = new ObservableCollection<DataItem>();
            }
            else
            {
                MeasureData.DataItems.Clear();
            }


            foreach(var keypair in DataDictFrequency_PositionCollection)
            {
                foreach(var value in keypair.Value)
                {
                    MeasureData.DataItems.Add(value);
                }
            }

            //找一个可用的文件名
            int i = 1;
            string directory = Path.GetDirectoryName(SaveAsName);
            string fileName = Path.GetFileName(SaveAsName);
            string fileExtension = Path.GetExtension(SaveAsName);
            fileName=fileName.Replace(fileExtension,"");
            string temp = "";
            while(true)
            {
                string name = fileName + "_Processed_" + i.ToString();
                if(File.Exists(Path.Combine(directory,name+fileExtension)))
                {
                    i++;
                }
                else
                {
                    temp = Path.Combine(directory, name+fileExtension);
                    break;
                }
            }    

            DataManage.WriteToFile(MeasureData, temp);
            GrowlInfo Info = new GrowlInfo();
            Info.WaitTime = 0;
            Info.Message = $"文件保存完毕!\n{temp}";
            Growl.Success(Info);
        }



        /// <summary>
        /// 将当前数据发送到结果分析页面，并跳转到结果分析页面
        /// </summary>
        /// <param name="obj"></param>
        [RelayCommand]
        public void Transfer(object obj)
        {
            if(string.IsNullOrEmpty(obj.ToString())) { return; }
            ResultAnalysis.ViewModel.LoadData(MeasureData);
            MainWindow.ViewModel.NavigationPage(obj.ToString());
        }




        //修复坏点，根据当前的频率 位置 数据类型

        [ObservableProperty]
        private double fix_Frequency;

        [ObservableProperty]
        private double fix_Position;

        [RelayCommand]
        public void FixPoint()
        {
            var F = DataDictFrequency_PositionCollection[Fix_Frequency];
            if (F == null) return;
            if (F.Count < 3) return;//点太少，处理无意义
            var properties = typeof(DataItem).GetProperties();
            foreach (var property in properties)
            {
                var displayNameAttribute = (DisplayNameAttribute)Attribute.GetCustomAttribute(property, typeof(DisplayNameAttribute));
                if (displayNameAttribute != null && displayNameAttribute.DisplayName == DataType)
                {
                    //找到属性
                    for (int i = 0; i < F.Count; i++)
                    {
                        if (F[i].Position == Fix_Position)
                        {
                            if (i == 0)
                            {
                                //第一点
                                property.SetValue(F[i], property.GetValue(F[i+1]));
                            }


                            else if (i == F.Count - 1)
                            {
                                //最后一点
                                property.SetValue(F[i], property.GetValue(F[i - 1]));
                            }
                            else
                            {
                                //取前后平均值
                                property.SetValue(F[i], ((double)property.GetValue(F[i + 1])+(double)property.GetValue(F[i - 1]))/2);
                            }
                            return;
                        }
                    }
                    break;
                }
            }
        }

        #endregion
    }
}
